package com.supermap.wzhy.module.user.service;

import com.supermap.wzhy.common.service.BaseService;
import com.supermap.wzhy.data.MessagePrintUtil;
import com.supermap.wzhy.data.cons.CMicroMetaType;
import com.supermap.wzhy.data.cons.CPowerDataType;
import com.supermap.wzhy.data.cons.CTree;
import com.supermap.wzhy.entity.*;
import com.supermap.wzhy.module.data.dao.MicroIdenmetaDao;
import com.supermap.wzhy.module.data.dao.MicroTablemetaDao;
import com.supermap.wzhy.module.user.dao.PowerCatalogsDao;
import com.supermap.wzhy.module.user.dao.PowerDao;
import com.supermap.wzhy.module.user.dao.UserRoleDao;
import com.supermap.wzhy.util.tree.DHTMLXTree;
import com.supermap.wzhy.util.tree.DHTMLXTreeFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户、角色权限入口
 *
 * @author Created by W.Qiong on 14-10-21.
 * @author Modified by Linhao on 15-02-28.
 */
@Service
public class UserRolePowerService extends BaseService {
    /** 权限dao */
    @Autowired
    private PowerDao powerDao;

    /** 用户角色dao */
    @Autowired
    private UserRoleDao userRoleDao;

    /** 权限分类dao */
    @Autowired
    private PowerCatalogsDao powerCatalogsDao;

    /** 基本指标配置信息dao */
    @Autowired
    private MicroIdenmetaDao microIdenmetaDao;


    /** 基层对象元数据信息dao */
    @Autowired
    private MicroTablemetaDao microTablemetaDao;

    /** 数据权限server */
    @Autowired
    private DataPowerService dataPowerService;

    /** 用户系统权限server */
    @Autowired
    private SysPowerService sysPowerService;

    /**
     * 获取指定用户id下所有权限的<b>树</b>结构
     *
     * @param userid
     *            指定用户id
     * @return 树结构{sys:..,data:...}
     */
    public Map<String, Object> getAllPowers(int userid) {
        Map<String, Object> re = new HashMap<>();

        // 系统权限树
        DHTMLXTree sys = getAllSysPowerDHTMLXTree();
        re.put("sys", DHTMLXTreeFactory.toTree(sys));

        // 数据权限树
        List<DHTMLXTree> roots = new ArrayList<>();
        re.put("data", DHTMLXTreeFactory.toTree((ArrayList<DHTMLXTree>) roots));

        return re;
    }

    /**
     * 取得系统权限列表树
     * <p>
     * 说明：<br/>
     * 从T_USERPOWERCATALOG表中获取所有的权限分类
     * </p>
     *
     * @return 系统权限列表树
     */
    private DHTMLXTree getAllSysPowerDHTMLXTree() {
        // 系统权限树
        List<TUserpowercatalog> powerCatalogs = powerCatalogsDao.findAll();
        DHTMLXTree sysPowerTree = new DHTMLXTree(CTree.ROOT_SYS, "系统权限列表")
                .noCheckbox().open();
        for (TUserpowercatalog powercatalog : powerCatalogs) {
            String id = powercatalog.getPcataid() + "_" + CTree.ROOT_SYS;
            DHTMLXTree node = new DHTMLXTree(id, powercatalog.getName())
                    .noCheckbox();
            sysPowerTree.add(node);
        }

        return sysPowerTree;
    }
    /**
     * 获取用户有所权限 包括（用户所有角色下的权限+用户特有权限）
     *
     * @param userId
     *            指定用户id
     *
     * @return 权限列表（用户所有角色下的权限+用户特有权限）
     */
    public List getUserAllPowers(int userId) {
        List<TUserpower> userpowers = powerDao
                .findUserpowerListByUserid(userId);

        // 用户下所有角色
        List roles = null;
        String sql = "select distinct * from t_userrole start with roleid in (select distinct u.roleid "
                + "from t_userrolerelation u where u.userid="
                + userId
                + ")"
                + "connect by prior roleid = parid";
        try {
            roles = userRoleDao.query(sql);
        } catch (Exception e) {
            MessagePrintUtil.printException(sql);
            e.printStackTrace();
        }
        if (roles != null && roles.size() > 0) {
            int[] roleids = new int[roles.size()];
            for (int i = 0, size = roles.size(); i < size; i++) {
                // 记录
                Object[] arr = (Object[]) roles.get(i);
                // 角色ID
                roleids[i] = Integer.parseInt(arr[0].toString());
            }

            // 根据用户角色(一个或者多个)id，找到权限列表信息(去重复)
            List<TUserpower> rolepowers = powerDao
                    .findUserpowerListByRoleids(roleids);
            // 合并去重（用户特有权限、用户角色权限）
            for (int j = 0, size = rolepowers.size(); j < size; j++) {
                TUserpower tup = rolepowers.get(j);
                // 去掉重复
                if (!userpowers.contains(tup)) {
                    userpowers.add(tup);
                }
            }
            if (rolepowers.size() < 1)
                MessagePrintUtil.printMsg("当前用户（" + userId + "）角色下没有关联权限!");
        } else {
            MessagePrintUtil.printMsg("当前用户（" + userId + "）角色未设置!");
        }// end if (roles != null && roles.size() > 0) else

        return userpowers;
    }

    /**
     * 根据用户角色id，找到角色下权限列表信息
     * <p>
     * 说明：<br/>
     * 从TRolepowerrelation 中查询到
     * </p>
     *
     * @param roleId
     *            指定角色id
     * @return 角色下权限列表信息
     */
    // public List getRolePowers(String selItem, int roleId){
    public List getRolePowers(int roleId) {
        return powerDao.findUserpowerListByRoleid(roleId);
    }

    /**
     * 权限列表树点击事件
     *
     * @param id
     *            用户id或者角色id
     * @param selItem
     *            选择的权限类型（结尾必须包含'_sys'、'_micro'或'_major'）
     * @param type
     *            权限类型区分（值为"u"或者"r"）
     * @return 指定条件下的权限列表
     */
    public List getPowerListByType(int id, String selItem, String type) {
        String[] selSplit = selItem.split("_");
        int len = selSplit.length;
        if (selSplit[len - 1].equals("sys")) {
            // 系统权限
            return getSysPowerList(id, selItem, type);
        } else if (selSplit[len - 1].equals("micro")) {
            // 基层数据权限
            return getMicroPowerList(id, selItem, type);
        }
        // else if(selSplit[len-1].equals("major")){
        // //基层专业数据权限
        // return getMicroMajorPowerList(userid, selItem, type);
        // }
        else if(selSplit[len - 1].equals("ht")){
            return  getHtPowerList(id,type) ;
        }
        else {
            // 综合数据权限
//            return getMacroPowerList(id, selItem, type);
            return  null ;
        }
    }

    /**
     * 获取指定条件下的系统权限列表
     *
     * @param id
     *            用户id或者角色id
     * @param selItem
     *            选择的权限类型（结尾必须包含'_sys'）
     * @param type
     *            权限类型区分（值为"u"或者"r"）
     * @return 系统权限列表
     */
    private List getSysPowerList(int id, String selItem, String type) {
        String[] selSplit = selItem.split("_");
        int len = selSplit.length;
        List<Map<String, String>> reList = new ArrayList<>();

        int selId = Integer.parseInt(selSplit[0]);
        // 获取系统权限列表 6 后台管理权限 树结构
        if (selSplit[0].equals("6")) {
            List<String> re = new ArrayList<>();
            re.add(getHtManagerTree(id, type));
            return re;
        }

        // 获取非6的权限结果
        List<TUserpower> result = powerDao.findPowerByCatalog(selId);
        Map<Integer, String> sysPowersMap = getUserOrRoleSysPower(id, selId,
                type);
        for (TUserpower p : result) {
            Map<String, String> map = new HashMap<>();
            int powerid = p.getPowerid();
            boolean isChecked = sysPowersMap.containsKey(powerid);
            map.put("id", powerid + "");
            map.put("name", p.getPowerName());
            map.put("value", p.getPowerValue());
            map.put("status", isChecked ? "checked" : "unchecked");
            reList.add(map);
        }
        return reList;
    }


    /**
     * 获取用户后台管理模块权限列表
     * @param id
     * @param type
     * @return
     */
    public List getHtPowerList(int id, String type) {
        List<Map<String, String>> reList = new ArrayList<>();
        //仅为模块
        List<TUserpower> powers = powerDao.findPowerByCatalog(6); //findByParid((6, CTree.ROOT_VALUE))
        Map<Integer, String> powerMap = getUserOrRoleSysPower(id, 6, type);
        for (TUserpower  p: powers) {
            Map<String, String> map = new HashMap<>();
            int powerid = p.getPowerid();
            boolean isChecked = powerMap.containsKey(powerid);
            map.put("id", powerid + "");
            map.put("name", p.getPowerName());
            map.put("value", p.getPowerValue());
            map.put("status", isChecked ? "checked" : "unchecked");
            reList.add(map);
        }
        return  reList ;
    }

    /**
     * 获取后台管理树( t.TUserpowercatalog.pcataid=6)
     *
     * @param id
     *            用户id（当参数type为"u"时）或者角色id（当参数type为"r"时）
     * @param type
     *            权限类型区分（值为"u"或者"r"）
     * @return 后台管理树
     */
    public String getHtManagerTree(int id, String type) {
        // 构造后台管理树 不只是两层结构？
        DHTMLXTree tree = new DHTMLXTree(CTree.ROOT_SDMS, "后台管理").open()
                .noCheckbox();
        List<TUserpower> powers = powerDao.findByParid(6, CTree.ROOT_VALUE);
        Map<Integer, String> map = getUserOrRoleSysPower(id, 6, type);
        for (TUserpower power : powers) {
            DHTMLXTree node = getHTMSubNode(power, map);
            tree.add(node);
        }
        return DHTMLXTreeFactory.toTree(tree);
    }

    /**
     * 获取指定用户id或者角色id下的系统权限
     *
     * @param id
     *            用户id（当参数type为"u"时）或者角色id（当参数type为"r"时）
     * @param selId
     *            权限分类id(pcataid)
     * @param type
     *            权限类型区分（值为"u"或者"r"）
     * @return 系统权限（去重复）{powerid：powerid}
     */
    private Map<Integer, String> getUserOrRoleSysPower(int id, int selId,
                                                       String type) {
        Map<Integer, String> sysPowersMap = new HashMap<>();
        if (type.equals("u")) { // 获取id用户所有权限
            int[] roleids = getUserAllRoles(id);
            sysPowersMap = sysPowerService.getUserSysPowers(id, selId, roleids);
        } else if (type.equals("r")) { // 获取id角色权限
            sysPowersMap = sysPowerService.getRoleSysPowers(id, selId);
        }
        return sysPowersMap;
    }

    /**
     * 获取后台管理树( t.TUserpowercatalog.pcataid=6)下的子节点（递归）
     *
     * @param par
     *            当前权限对象
     * @param map
     *            指定用户id或者角色id下的系统权限
     *
     * @return DHTMLXTree对象
     */
    private DHTMLXTree getHTMSubNode(TUserpower par, Map<Integer, String> map) {
        DHTMLXTree root = new DHTMLXTree(Integer.toString(par.getPowerid()),
                par.getPowerName());
        int parid = par.getPowerid();
        List<TUserpower> subPowers = powerDao.findByParid(6, parid);
        boolean subChecked = false;
        for (TUserpower subPower : subPowers) {
            if (map.containsKey(subPower.getPowerid())) {
                subChecked = true;
            }
            DHTMLXTree subNode = getHTMSubNode(subPower, map);
            root.add(subNode);
        }
        if (subPowers.size() > 0) {
            root.open();
        }
        // 子节点有选中或者该节点有选中
        if (map.containsKey(parid) || subChecked) {
            root.checked();
        }
        return root;
    }

    /**
     * 获取指定条件下的基层数据权限
     *
     * @param id
     *            用户id或者角色id
     * @param selItem
     *            选择的元素（基层调查对象[mitmid]_.. 或者[mitmid])
     * @param type
     *            权限类型区分（值为"u"或者"r"）
     * @return 基层数据权限列表
     */
    private List getMicroPowerList(int id, String selItem, String type) {
        String[] selSplit = selItem.split("_");
        int len = selSplit.length;
        List<Map<String, String>> reList = new ArrayList<>();
        if (len > 1) {
            int selId = Integer.parseInt(selSplit[0]);
            // 某个调查对象指标权限
            List<TMicroIdenmeta> result = microIdenmetaDao
                    .findObjectIdens(selId);
            Map<Integer, String> powerMap = getUserOrRoleDataPower(id,
                    CPowerDataType.MICRO_IDE, type);
            for (TMicroIdenmeta p : result) {
                Map<String, String> map = new HashMap<>();
                boolean isChecked = powerMap.containsKey(p.getMiimid());
                map.put("id", p.getMiimid() + "");
                map.put("name", p.getIdenName());
                map.put("status", isChecked ? "checked" : "unchecked");
                reList.add(map);
            }
        } else {
            // 获取调查对象列表
            List<TMicroTablemeta> tablemetas = microTablemetaDao
                    .findByMicmetaType(CMicroMetaType.OBJECT_TYPE);
            Map<Integer, String> powerMap = getUserOrRoleDataPower(id,
                    CPowerDataType.MICRO_SUERVER, type);
            for (TMicroTablemeta p : tablemetas) {
                Map<String, String> map = new HashMap<>();
                int mitmid = p.getMitmid();
                boolean isChecked = powerMap.containsKey(mitmid);
                map.put("id", mitmid + "");
                map.put("name", p.getName());
                map.put("status", isChecked ? "checked" : "unchecked");
                reList.add(map);
            }
        }// end if (len > 1)

        return reList;
    }

    /**
     * 获取指定用户id或者角色id下的数据权限
     *
     * @param id
     *            用户id（当参数type为"u"时）或者角色id（当参数type为"r"时）
     * @param selId
     *            权限分类id(由CPowerDataType提供)
     * @param type
     *            权限类型区分（值为"u"或者"r"）
     * @return 系统权限（去重复）{dataid：dataid}
     */
    private Map<Integer, String> getUserOrRoleDataPower(int id, int selId,
                                                        String type) {
        Map<Integer, String> dataPowersMap = new HashMap<>();
        if (type.equals("u")) {
            int[] roleids = getUserAllRoles(id);
            dataPowersMap = dataPowerService.getUserPowerByType(id, selId,
                    roleids);
        } else if (type.equals("r")) {
            dataPowersMap = dataPowerService.getRolePowerByType(id, selId);
        }
        return dataPowersMap;
    }

    /**
     * 获取用户的某类数据权限(去重复)
     *
     * @param userid
     * 			用户id
     * @param dataType
     * 			dataType 数据类型（基层或者综合）
     * @return 权限(指定类型下的所有权限,去重复) {dataid:'dataid'}
     */
    public Map getPowerMapByDataType(int userid, int dataType) {
        int[] roleids = getUserAllRoles(userid);
        return dataPowerService.getUserPowerByType(userid, dataType, roleids);
    }

    /**
     * 设置用户或者角色的权限入口
     *
     * @param id
     *          用户id或者角色id
     * @param selItem
     *          选择的权限类型（结尾必须包含'_sys'、或parid）
     * @param dataids
     * 			  要设置的权限id
     * @param type
     *            权限类型区分（值为"u"或者"r"）
     * @return 是否设置成功
     */
    public boolean setPowers(int id, String selItem, int[] dataids, String type) {
        if (type.equals("u")) {
            return setUserPowers(id, selItem, dataids);
        } else if (type.equals("r")) {
            return setRolePowers(id, selItem, dataids);
        }
        return false;
    }

    /**
     * 设置指定用户id的权限
     * @param userid
     * 			用户id
     * @param selItem
     *          选择的权限类型（结尾必须包含'_sys'、或parid）
     * @param dataids
     * 			  要设置的权限id
     * @return 是否设置成功
     */
    private boolean setUserPowers(int userid, String selItem, int[] dataids) {
        String[] selSplit = selItem.split("_");
        int len = selSplit.length;
        if (selSplit[len - 1].equals("sys")) {
            int pcataid = Integer.parseInt(selSplit[0]);
            return sysPowerService.setUserSysPowers(userid, dataids, pcataid);
        } else {
            return dataPowerService.setUserPowers(userid, dataids, selItem);
        }
    }

    /**
     * 设置指定用户id的权限
     * @param roleid
     * 			角色id
     * @param selItem
     *          选择的权限类型（结尾必须包含'_sys'、或parid）
     * @param dataids
     * 			  要设置的权限id
     * @return 是否设置成功
     */
    private boolean setRolePowers(int roleid, String selItem, int[] dataids) {
        String[] selSplit = selItem.split("_");
        int len = selSplit.length;
        if (selSplit[len - 1].equals("sys")) {
            int pcataid = Integer.parseInt(selSplit[0]);
            return sysPowerService.setRoleSysPowers(roleid, dataids, pcataid);
        } else {
            return dataPowerService.setRolePowers(roleid, dataids, selItem);
        }
    }

    /**
     * 添加单个数据权限 创建数据对象
     *
     * @param user
     * 			指定用户对象
     * @param dataIds
     * 			数据权限id
     * @param dataType
     * 			数据类型 基层/综合(由CPowerDataTypechang中常量指定)
     * @return 是否添加成功
     */
    public boolean addUserPowers(TUsers user, int[] dataIds, int dataType) {
        return dataPowerService.addUserPowers(user, dataIds, dataType);
    }

    /**
     * 删除单个数据权限 删除数据对象
     *
     * @param userid
     * @param dataIds
     * @param dataType
     * @return
     */
    public boolean delUserPowers(int userid, int[] dataIds, int dataType) {
        return dataPowerService.delUserPowers(userid, dataIds, dataType);
    }

    /**
     * 获取用户下所有的角色 包括角色下的角色
     *
     * @param userId
     * 			指定用户id
     * @return 角色id
     */
    private int[] getUserAllRoles(int userId) {
        List roles = null;					// 用户下所有角色
        String sql = "select distinct * from t_userrole where roleid in (select distinct u.roleid "
                + "from t_userrolerelation u where u.userid="
                + userId
                + ")";/*
                + "connect by prior roleid = parid";*/
        try {
            roles = userRoleDao.query(sql);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (roles.size() > 0) {
            int[] roleids = new int[roles.size()];
            for (int i = 0, size = roles.size(); i < size; i++) {
                Object[] arr = (Object[]) roles.get(i);// 记录
                roleids[i] = Integer.parseInt(arr[0].toString());// 角色ID
            }
            return roleids;
        }
        return new int[0];
    }

    /**
     * 过滤当前用户下授权的指标项
     * @param currUser 当前用户
     * @param idenmetas 需要过滤指标
     * */
    public List<TMicroIdenmeta> getUserMicroIdenmeta(TUsers currUser, List<TMicroIdenmeta> idenmetas){
        List<TMicroIdenmeta> re = new ArrayList<>();
        //用户数据权限下的调查对象指标
        Map<Integer,String> powers = getPowerMapByDataType(currUser.getUserid(), CPowerDataType.MICRO_IDE);
        for(TMicroIdenmeta t:idenmetas){
            if(!powers.containsKey(t.getMiimid())){//权限编码：指标ID
                continue;
            }
            re.add(t);
        }
        if(idenmetas.size()<1) {
            System.out.println("当前基层数据，未配置有效指标");
        }else if(re.size()<1) {
            System.out.println("“" + idenmetas.get(0).getTMicroTablemeta().getName() + "”指标：未设置数据权限");
        }
        return re;
    }

}
